package com.atguigu.tingshu.search.service.impl;

import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch._types.FieldValue;
import co.elastic.clients.elasticsearch._types.SortOptions;
import co.elastic.clients.elasticsearch._types.SortOrder;
import co.elastic.clients.elasticsearch._types.aggregations.Aggregate;
import co.elastic.clients.elasticsearch._types.query_dsl.BoolQuery;
import co.elastic.clients.elasticsearch._types.query_dsl.Query;
import co.elastic.clients.elasticsearch.core.SearchRequest;
import co.elastic.clients.elasticsearch.core.SearchResponse;
import co.elastic.clients.elasticsearch.core.search.CompletionSuggest;
import co.elastic.clients.elasticsearch.core.search.Hit;
import co.elastic.clients.elasticsearch.core.search.Suggestion;
import co.elastic.clients.json.JsonData;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.atguigu.tingshu.album.client.AlbumInfoFeignClient;
import com.atguigu.tingshu.album.client.CategoryFeignClient;
import com.atguigu.tingshu.common.constant.RedisConstant;
import com.atguigu.tingshu.common.result.Result;
import com.atguigu.tingshu.common.util.PinYinUtils;
import com.atguigu.tingshu.model.album.*;

import com.atguigu.tingshu.model.search.AlbumInfoIndex;
import com.atguigu.tingshu.model.search.AttributeValueIndex;
import com.atguigu.tingshu.model.search.SuggestIndex;
import com.atguigu.tingshu.query.search.AlbumIndexQuery;
import com.atguigu.tingshu.search.repository.AlbumIndexRepository;
import com.atguigu.tingshu.search.repository.SuggestIndexRepository;
import com.atguigu.tingshu.search.service.SearchService;
import com.atguigu.tingshu.user.client.UserInfoFeignClient;
import com.atguigu.tingshu.vo.search.AlbumInfoIndexVo;
import com.atguigu.tingshu.vo.search.AlbumSearchResponseVo;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import io.swagger.v3.core.util.Json;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.core.suggest.Completion;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;


@Slf4j
@Service
@SuppressWarnings({"all"})
public class SearchServiceImpl implements SearchService {


    @Autowired
    private AlbumInfoFeignClient albumInfoFeignClient;

    @Autowired
    private CategoryFeignClient categoryFeignClient;

    @Autowired
    private UserInfoFeignClient userInfoFeignClient;
    //  内嵌了很多api 方法，同时启动的时候还会根据实体类的属性注解自动生成mapping结构,索引库！
    @Autowired
    private AlbumIndexRepository albumIndexRepository;

    @Autowired
    private ThreadPoolExecutor threadPoolExecutor;

    @Autowired
    private ElasticsearchClient elasticsearchClient;

    @Autowired
    private SuggestIndexRepository suggestIndexRepository;

    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public List<AlbumInfoIndex> findRankingList(Long category1Id, String ranking) {
        //从缓存中取数据
        List<AlbumInfoIndex> albumInfoIndexList = (List<AlbumInfoIndex>)redisTemplate.opsForHash().get(RedisConstant.RANKING_KEY_PREFIX + category1Id, ranking);
        return albumInfoIndexList;
    }

    /**
     * 更新排行榜
     */
    @SneakyThrows
    @Override
    public void updateLatelyAlbumRanking() {
        //获取一级分类id
        Result<List<BaseCategory1>> allCategory1 = categoryFeignClient.findAllCategory1();
        //判断
        Assert.notNull(allCategory1, "一级分类为空");
        List<BaseCategory1> category1List = allCategory1.getData();
        //判断
        Assert.notNull(category1List, "一级分类集合为空");

        for (BaseCategory1 baseCategory1 : category1List) {
            //  五个维度
            String[] rankingDimensionArray = new String[]{"hotScore", "playStatNum", "subscribeStatNum", "buyStatNum", "commentStatNum"};
            for (String ranking: rankingDimensionArray) {
                //创建dsl语句
                    SearchResponse<AlbumInfoIndex> searchResponse = elasticsearchClient.search(s -> s.index("albuminfo")
                            .query(q -> q.term(t -> t.field("category1Id").value(baseCategory1.getId())))
                            .sort(SortOptions.of(so -> so.field(f -> f.field(ranking).order(SortOrder.Desc)))), AlbumInfoIndex.class);

                List<AlbumInfoIndex> albumInfoIndexList = searchResponse.hits().hits().stream().map(Hit::source).collect(Collectors.toList());
                //将数据存入到缓存中hset key field value  key就是category1id，field就是每一个维度，value就是对应的数据
                redisTemplate.opsForHash().put(RedisConstant.RANKING_KEY_PREFIX+baseCategory1.getId(),ranking,albumInfoIndexList);
            }
        }
    }

    @Override
    public List<String> completeSuggest(String keyword) {

        /*//todo 生成构建dsl语句对象
        SearchRequest.Builder searchRequestBuilder = new SearchRequest.Builder();
        searchRequestBuilder.index("suggestinfo");
        searchRequestBuilder.suggest(su->su.suggesters("suggestionKeyword", sugg->sugg.completion(c->c.field("keyword").skipDuplicates(true)).prefix(keyword)))
                .suggest(su->su.suggesters("suggestionkeywordPinyin", sugg->sugg.completion(c->c.field("keywordPinyin").skipDuplicates(true)).prefix(keyword)))
                .suggest(su->su.suggesters("suggestionkeywordSequence", sugg->sugg.completion(c->c.field("keywordSequence").skipDuplicates(true)).prefix(keyword)));

        SearchRequest searchRequest = searchRequestBuilder.build();
        System.out.println("语句==============" + searchRequest);
        //响应对象
        SearchResponse<SuggestIndex> searchResponse = null;
        try {
            searchResponse = elasticsearchClient.search(searchRequest, SuggestIndex.class);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        //接收数据
        HashSet<String> titleSuggest = new HashSet<>();
        titleSuggest.addAll(this.responseResult(searchResponse, "suggestionKeyword"));
        titleSuggest.addAll(this.responseResult(searchResponse, "suggestionkeywordPinyin"));
        titleSuggest.addAll(this.responseResult(searchResponse, "suggestionkeywordSequence"));


        return new ArrayList<>(titleSuggest);*/
        //  用客户端生成dsl语句！
        SearchResponse<SuggestIndex> searchResponse = null;
        try {
            searchResponse = elasticsearchClient.search(r -> r.index("suggestinfo")
                            .suggest(s -> s.suggesters("ts-suggest-keyword",
                                            s1 -> s1.prefix(keyword).completion(c -> c.field("keyword")
                                                    .fuzzy(f -> f.fuzziness("auto"))
                                                    .skipDuplicates(true)))
                                    .suggesters("ts-suggest-keywordPinyin",
                                            s1 -> s1.prefix(keyword).completion(c -> c.field("keywordPinyin")
                                                    .fuzzy(f -> f.fuzziness("auto"))
                                                    .skipDuplicates(true)))
                                    .suggesters("ts-suggest-keywordSequence",
                                            s1 -> s1.prefix(keyword).completion(c -> c.field("keywordSequence")
                                                    .fuzzy(f -> f.fuzziness("auto"))
                                                    .skipDuplicates(true)))
                            )
                    ,
                    SuggestIndex.class);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        //  获取数据
        List<String> list = new ArrayList<>();
        list.addAll(this.getSuggestTitle(searchResponse, "ts-suggest-keyword"));
        list.addAll(this.getSuggestTitle(searchResponse, "ts-suggest-keywordPinyin"));
        list.addAll(this.getSuggestTitle(searchResponse, "ts-suggest-keywordSequence"));
        //  返回集合
        return list;
    }

    private Collection<String> getSuggestTitle(SearchResponse<SuggestIndex> searchResponse, String keyword) {
        /*//创建集合
        List<String> suggestList = new ArrayList<>();

        Map<String, List<Suggestion<SuggestIndex>>> groupBySuggestionListAggMap = searchResponse.suggest();
        groupBySuggestionListAggMap.get(keyword).forEach(item -> {
            CompletionSuggest<SuggestIndex> completionSuggest =  item.completion();
            completionSuggest.options().forEach(it -> {
                SuggestIndex suggestIndex = it.source();
                suggestList.add(suggestIndex.getTitle());
            });
        });
        //  返回集合列表
        return suggestList;*/
        List<Suggestion<SuggestIndex>> suggestionList = searchResponse.suggest().get(keyword);
        for (Suggestion<SuggestIndex> suggestIndexSuggestion : suggestionList) {
            //  获取数据
            List<String> list = suggestIndexSuggestion.completion().options().stream().map(suggestIndexCompletionSuggestOption -> {
                return suggestIndexCompletionSuggestOption.source().getTitle();
            }).collect(Collectors.toList());
            //  返回数据
            return list;
        }
        return null;
    }

    /**
     * 获取一级分类下的热门排行专辑
     *
     * @param category1Id
     * @return
     */
    @Override
    public List<Map<String, Object>> channel(Long category1Id) {
        //根据一级分类id获取三级分类集合
        Result<List<BaseCategory3>> BaseCategory3Result = categoryFeignClient.findTopBaseCategory3(category1Id);
        //获取List<category3>数据
        List<BaseCategory3> category3ResultData = BaseCategory3Result.getData();
        //获取category3的id集合
        List<Long> category3IdList = category3ResultData.stream().map(BaseCategory3::getId).collect(Collectors.toList());
        //前端想要BaseCategory3对象，所以要将category3ResultData转换成map,ids作为key，对象作为value
        Map<Long, BaseCategory3> category3ToMap = category3ResultData.stream().collect(Collectors.toMap(BaseCategory3::getId, baseCategory3 -> baseCategory3));

        //将3id集合转换成查询语句想要的类型
        List<FieldValue> fieldValueList = category3IdList.stream().map(category3Id -> FieldValue.of(category3Id)).collect(Collectors.toList());
        //todo 创建语句(看写的语句)
        //创建searchrequest对象用于创建dsl语句
        SearchRequest.Builder searchRequestBuilder = new SearchRequest.Builder();
        //连接索引库
        searchRequestBuilder.index("albuminfo")
                .query(q -> q.terms(ts -> ts.field("category3Id")
                        .terms(t -> t.value(fieldValueList))))
                .aggregations("groupByCategory3IdAgg", agg -> agg.terms(at -> at.field("category3Id").size(6))
                        .aggregations("topTenHotScoreAgg",agg2->agg2.topHits(th->th.size(6)
                                .sort(SortOptions.of(s->s.field(f->f.field("hotScore").order(SortOrder.Desc)))))));

        SearchRequest searchRequest = searchRequestBuilder.build();

        //todo 执行查询
        SearchResponse<AlbumInfoIndex> searchResponse =null;
        try {
            searchResponse= elasticsearchClient.search(searchRequest, AlbumInfoIndex.class);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        //todo 获取结果集(看执行结果)
        //创建承载返回数据的集合
        List<Map<String, Object>> mapList = new ArrayList<>();
        Aggregate groupByCategory3IdAgg = searchResponse.aggregations().get("groupByCategory3IdAgg");
        groupByCategory3IdAgg.lterms().buckets().array().forEach(bucket->{
            //创建albumInfoIndex集合
            List<AlbumInfoIndex> albumInfoIndexList=new ArrayList<>();
            Aggregate topTenHotScoreAgg = bucket.aggregations().get("topTenHotScoreAgg");
            //取专辑对象
            topTenHotScoreAgg.topHits().hits().hits().forEach(hit->{
                //拿到了category3对应的json对象
                String source = hit.source().toString();
                //将source(专辑对象)转换成java对象
                AlbumInfoIndex albumInfoIndex = JSON.parseObject(source, AlbumInfoIndex.class);

                albumInfoIndexList.add(albumInfoIndex);
            });
            //前端需要的类型
            Map<String, Object> map = new HashMap<>();
            //获取category3对象
            map.put("baseCategory3", category3ToMap.get(bucket.key()));
            //将albumInfoIndexList加入到map中
            map.put("list", albumInfoIndexList);
            //加入到返回集合中
            mapList.add(map);
        });

        //返回数据
        return mapList;
    }

    /**
     * 专辑检索
     *
     * @param albumIndexQuery
     * @return
     */
    @SneakyThrows
    @Override
    public AlbumSearchResponseVo search(AlbumIndexQuery albumIndexQuery) {

        //todo 构建dsl语句
        SearchRequest searchRequest = this.createDsl(albumIndexQuery);

        System.out.println("searchRequest = " + searchRequest);

        //todo 调用查询方法
        SearchResponse<AlbumInfoIndex> searchResponse = elasticsearchClient.search(searchRequest, AlbumInfoIndex.class);
        //todo 得到结果集
        AlbumSearchResponseVo responseVo = this.searchResult(searchResponse);

        //设置记录总条数
        responseVo.setTotal(searchResponse.hits().total().value());
        //设置每页显示的内容size
        responseVo.setPageSize(albumIndexQuery.getPageSize());
        //设置当前页面no
        responseVo.setPageNo(albumIndexQuery.getPageNo());
        //设置totalpages总共多少页
        Long l = responseVo.getTotal() % responseVo.getPageSize();
        responseVo.setTotalPages(l != 0 ? l + 1 : l);
        /*//  总页数 10 3 4   9 3 3
        responseVo.setTotalPages((responseVo.getTotal() + responseVo.getPageSize() - 1) / responseVo.getPageSize());*/
        //todo 返回结果集
        return responseVo;
    }

    private AlbumSearchResponseVo searchResult(SearchResponse<AlbumInfoIndex> searchResponse) {
        /*//创建AlbumSearchResponseVo对象
        AlbumSearchResponseVo searchResponseVo = new AlbumSearchResponseVo();

        //获取数据
        List<Hit<AlbumInfoIndex>> hits = searchResponse.hits().hits();
        List<AlbumInfoIndexVo> collect = hits.stream().map(hit -> {
            AlbumInfoIndex albumInfoIndex = hit.source();
            //创建AlbumInfoIndexVo对象
            AlbumInfoIndexVo albumInfoIndexVo = new AlbumInfoIndexVo();
            //属性赋值
            BeanUtils.copyProperties(albumInfoIndex, albumInfoIndexVo);
            //获取高亮
            if (null != hit.highlight().get("albumTitle")) {
                //获取高亮标题
                String albumTitle = hit.highlight().get("albumTitle").get(0);
                albumInfoIndexVo.setAlbumTitle(albumTitle);
            }
            return albumInfoIndexVo;
        }).collect(Collectors.toList());

        searchResponseVo.setList(collect);

        return searchResponseVo;*/
        //  主要给 private List<AlbumInfoIndexVo> list = new ArrayList<>(); 属性赋值;
        AlbumSearchResponseVo albumSearchResponseVo = new AlbumSearchResponseVo();
        //  获取数据
        List<Hit<AlbumInfoIndex>> hits = searchResponse.hits().hits();
        List<AlbumInfoIndexVo> list = hits.stream().map(hit -> {
            //  创建对象
            AlbumInfoIndexVo albumInfoIndexVo = new AlbumInfoIndexVo();
            //  获取到source
            AlbumInfoIndex albumInfoIndex = hit.source();
            //  赋值：
            BeanUtils.copyProperties(albumInfoIndex, albumInfoIndexVo);
            //  判断当前用户是否根据关键词进行检索，应该获取到高亮字段.
            if (null != hit.highlight().get("albumTitle")) {
                //  获取高亮标题
                String albumTitle = hit.highlight().get("albumTitle").get(0);
                //  赋值
                albumInfoIndexVo.setAlbumTitle(albumTitle);
            }
            //  返回数据
            return albumInfoIndexVo;
        }).collect(Collectors.toList());
        //  赋值；
        albumSearchResponseVo.setList(list);
        //  返回数据
        return albumSearchResponseVo;
    }

    /**
     * 构建dsl语句
     *
     * @param albumIndexQuery
     * @return
     */
    private SearchRequest createDsl(AlbumIndexQuery albumIndexQuery) {
/*        //创建searchRequest对象
        SearchRequest.Builder searchBuilder = new SearchRequest.Builder();
        //靠近索引库
        searchBuilder.index("albumInfo");
        //构建query对象
        Query.Builder queryBuilder = new Query.Builder();
        //构建bool对象
        BoolQuery.Builder boolBuilder = new BoolQuery.Builder();
        //todo 检索关键词
        if(!StringUtils.isEmpty(albumIndexQuery.getKeyword())){
            boolBuilder.should(s -> s.match(m -> m.field("albumtTitle").query(albumIndexQuery.getKeyword())))
                    .should(s -> s.match(m -> m.field("albumtInfo").query(albumIndexQuery.getKeyword())))
                    .should(s -> s.match(m -> m.field("announcerName").query(albumIndexQuery.getKeyword())));
            //设置高亮
            searchBuilder.highlight(h->h.fields("albumTitle",ht->ht.preTags("<span style=color:red>").postTags("</span>")));
        }
        //todo 检索分类Id
        if(null !=albumIndexQuery.getCategory3Id()){
            boolBuilder.filter(f->f.term(t->t.field("category3Id").value(albumIndexQuery.getCategory3Id())));
        }

        //todo 检索属性

        BoolQuery boolBuild = boolBuilder.build();
        queryBuilder.bool(boolBuild);//需要一个bool对象

        Query queryBuild = queryBuilder.build();
        searchBuilder.query(queryBuild);//需要quwey对象

        SearchRequest searchRequest = searchBuilder.build();
        return searchRequest;*/
        //创建dsl对象
        SearchRequest.Builder searchBuilder = new SearchRequest.Builder();//靠近index

        searchBuilder.index("albuminfo");
        //创建query对象
        Query.Builder queryBuilder = new Query.Builder();
        //创建boolquery对象
        BoolQuery.Builder boolBuilder = new BoolQuery.Builder();
//        if (!StringUtils.isEmpty(albumIndexQuery.getKeyword())) {
//            //有关键词
//            boolBuilder.should(f -> f.term(m -> m.field("albumTitle").query(albumIndexQuery.getKeyword()))).should(f -> f.match(m -> m.field("albumIntro").query(albumIndexQuery.getKeyword()))).should(f -> f.match(m -> m.field("announcerName").query(albumIndexQuery.getKeyword())));
//            //对关键词添加高亮
//            searchBuilder.highlight(h -> h.fields("albumTitle", ht -> ht.preTags("<span style=color:red>").postTags("</span>")));
//        }
        if (!StringUtils.isEmpty(albumIndexQuery.getKeyword())){
            boolBuilder.should(f -> f.term(m -> m.field("albumTitle").value(albumIndexQuery.getKeyword())))
                    .should(f -> f.term(m -> m.field("albumIntro").value(albumIndexQuery.getKeyword())))
                    .should(f -> f.term(m -> m.field("announcerName").value(albumIndexQuery.getKeyword())));
            searchBuilder.highlight(h->h.fields("albumTitle",ht->ht.preTags("<span style=color:red>").postTags("</span>")));
        }

        //根据分类id进行检索
        if (null != albumIndexQuery.getCategory3Id()) {
            //用户点击了3级分类
            boolBuilder.filter(f -> f.term(t -> t.field("category3Id").value(albumIndexQuery.getCategory3Id())));
        }
        if (null != albumIndexQuery.getCategory2Id()) {
            //用户点击了2级分类
            boolBuilder.filter(f -> f.term(t -> t.field("category2Id").value(albumIndexQuery.getCategory2Id())));
        }
        if (null != albumIndexQuery.getCategory1Id()) {
            //用户点击了1级分类
            boolBuilder.filter(f -> f.term(t -> t.field("category1Id").value(albumIndexQuery.getCategory1Id())));
        }

        //根据属性值进行检索
        //获取属性属性值列表
        List<String> attributeList = albumIndexQuery.getAttributeList();
        //因为这里的list集合存储的是String类型,且格式是--->属性:属性值的格式存储的
        //我们可以进行分割来分别获取到属性和属性值
        if (!CollectionUtils.isEmpty(attributeList)) {
            for (String attribute : attributeList) {
                String[] split = attribute.split(":");
                if (null != split && split.length == 2) {
                    boolBuilder.filter(f -> f.nested(n -> n.path("attributeValueIndexList").query(q -> q.bool(b -> b.filter(bf -> bf.term(t -> t.field("attributeValueIndexList.attributeId").value(split[0]))).filter(f1 -> f1.term(ft -> ft.field("attributeValueIndexList.valueId").value(split[1])))))));
                }
            }
        }


        //进行分页
        //定义起始页
        int form = (albumIndexQuery.getPageNo() - 1) * albumIndexQuery.getPageSize();
        searchBuilder.from(form);
        searchBuilder.size(albumIndexQuery.getPageSize());

        //进行排序
        //获取用户选择的排序规则
        String order = albumIndexQuery.getOrder();
        String[] split = order.split(":");
        if (null != split && split.length == 2) {
            String str = "";
            switch (split[0]) {
                case "1":
                    str = "hotScore";
                    break;
                case "2":
                    str = "playStatNum";
                    break;
                case "3":
                    str = "createTime";
                    break;
            }
            //获取到排序方式
            String sortStr = str;
            searchBuilder.sort(s -> s.field(f -> f.field(sortStr).order("asc".equals(split[1]) ? SortOrder.Asc : SortOrder.Desc)));
        }

        BoolQuery build = boolBuilder.build();

        queryBuilder.bool(build);

        Query query = queryBuilder.build();

        //调用query
        searchBuilder.query(query);

        //构建requestBuild对象
        SearchRequest searchRequest = searchBuilder.build();

        System.out.println("dsl" + searchRequest.toString());
        return searchRequest;
    }

    /**
     * 上架专辑
     *
     * @param albumId
     */
    @Override
    public void upperAlbum(Long albumId) {
        //todo 创建albumInfoIndex对象
        AlbumInfoIndex albumInfoIndex = new AlbumInfoIndex();
        CompletableFuture<AlbumInfo> albumInfoCompletableFuture = CompletableFuture.supplyAsync(() -> {
            //  获取专辑信息.
            Result<AlbumInfo> infoResult = albumInfoFeignClient.getAlbumInfo(albumId);
            //  获取数据
            Assert.notNull(infoResult, "专辑信息结果集为空");
            AlbumInfo albumInfo = infoResult.getData();
            Assert.notNull(albumInfo, "专辑信息为空");
            //  属性拷贝：
            BeanUtils.copyProperties(albumInfo, albumInfoIndex);
            return albumInfo;
        }, threadPoolExecutor);


        //  获取分类数据
        CompletableFuture<Void> categoryCompletableFuture = albumInfoCompletableFuture.thenAcceptAsync(albumInfo -> {
            //  根据三级分类Id获取到分类视图对象.
            Result<BaseCategoryView> baseCategoryViewResult = categoryFeignClient.getCategoryView(albumInfo.getCategory3Id());
            Assert.notNull(baseCategoryViewResult, "分类结果集为空");
            BaseCategoryView baseCategoryView = baseCategoryViewResult.getData();
            Assert.notNull(baseCategoryView, "分类视图对象为空");
            albumInfoIndex.setCategory1Id(baseCategoryView.getCategory1Id());
            albumInfoIndex.setCategory2Id(baseCategoryView.getCategory2Id());
        }, threadPoolExecutor);


       /* CompletableFuture<Void> userCompletableFuture = albumInfoCompletableFuture.thenAcceptAsync(albumInfo -> {
            //todo 根据用户id获取用户信息
            Result<UserInfoVo> userInfoVoResult = userInfoFeignClient.getUserInfoVoByUserId(albumInfo.getUserId());
            UserInfoVo userInfoVo = userInfoVoResult.getData();
            Assert.notNull(userInfoVo, "用户信息为空");
        },threadPoolExecutor);*/
        //  获取用户信息
        CompletableFuture<Void> userCompletableFuture = albumInfoCompletableFuture.thenAcceptAsync(albumInfo -> {
            Result<UserInfoVo> userInfoVoResult = userInfoFeignClient.getUserInfoVoByUserId(albumInfo.getUserId());
            Assert.notNull(userInfoVoResult, "用户信息查询失败");
            UserInfoVo userInfoVo = userInfoVoResult.getData();
            Assert.notNull(userInfoVo, "用户信息为空");
            albumInfoIndex.setAnnouncerName(userInfoVo.getNickname());
        }, threadPoolExecutor);



       /* CompletableFuture<Void> attrCompletableFuture = CompletableFuture.runAsync(() -> {
            //todo 根据Id获取属性信息
            Result<List<AlbumAttributeValue>> albumAttributeValueResult = albumInfoFeignClient.findAlbumAttributeValue(albumId);
            List<AlbumAttributeValue> albumAttributeValueList = albumAttributeValueResult.getData();
            Assert.notEmpty(albumAttributeValueList, "属性信息为空");
            //赋值属性信息
            //判断属性信息是否为空
            if (!CollectionUtils.isEmpty(albumAttributeValueList)) {
                List<AttributeValueIndex> attributeValueIndexList = albumAttributeValueList.stream().map(albumAttributeValue -> {
                    //创建对象
                    AttributeValueIndex attributeValueIndex = new AttributeValueIndex();
                    attributeValueIndex.setAttributeId(albumAttributeValue.getAttributeId());
                    attributeValueIndex.setValueId(albumAttributeValue.getValueId());
                    return attributeValueIndex;
                }).collect(Collectors.toList());

                //保存数据
                albumInfoIndex.setAttributeValueIndexList(attributeValueIndexList);
            }
        }, threadPoolExecutor);*/
        //  属性赋值：
        CompletableFuture<Void> attrCompletableFuture = CompletableFuture.runAsync(() -> {
            Result<List<AlbumAttributeValue>> listResult = albumInfoFeignClient.findAlbumAttributeValue(albumId);
            Assert.notNull(listResult, "属性值结果集为空");
            List<AlbumAttributeValue> albumAttributeValueList = listResult.getData();
            Assert.notNull(albumAttributeValueList, "属性值为空");
            //  albumAttributeValueList 循环遍历当前集合，获取到  attributeId  valueId 给 albumInfoIndex 中的属性赋值！
            List<AttributeValueIndex> attributeValueIndexList = albumAttributeValueList.stream().map(albumAttributeValue -> {
                //  创建对象
                AttributeValueIndex attributeValueIndex = new AttributeValueIndex();
                attributeValueIndex.setAttributeId(albumAttributeValue.getAttributeId());
                attributeValueIndex.setValueId(albumAttributeValue.getValueId());
                //  返回数据
                return attributeValueIndex;
            }).collect(Collectors.toList());
            //  赋值数据了.
            albumInfoIndex.setAttributeValueIndexList(attributeValueIndexList);
        }, threadPoolExecutor);

        //更新统计量
        albumInfoIndex.setPlayStatNum(new Random().nextInt(10000));
        albumInfoIndex.setSubscribeStatNum(new Random().nextInt(10000));
        albumInfoIndex.setBuyStatNum(new Random().nextInt(10000));
        albumInfoIndex.setCommentStatNum(new Random().nextInt(10000));

        CompletableFuture.allOf(albumInfoCompletableFuture, categoryCompletableFuture, userCompletableFuture, attrCompletableFuture).join();

        //将对象保存到es中
        albumIndexRepository.save(albumInfoIndex);


        //  上架添加提词数据.
//  创建对象 专辑标题提词
        SuggestIndex suggestIndex = new SuggestIndex();
        suggestIndex.setId(UUID.randomUUID().toString().replaceAll("-",""));
        suggestIndex.setTitle(albumInfoIndex.getAlbumTitle());
        suggestIndex.setKeyword(new Completion(new String[]{albumInfoIndex.getAlbumTitle()}));
        suggestIndex.setKeywordPinyin(new Completion(new String[]{PinYinUtils.toHanyuPinyin(albumInfoIndex.getAlbumTitle())}));
        suggestIndex.setKeywordSequence(new Completion(new String[]{PinYinUtils.getFirstLetter(albumInfoIndex.getAlbumTitle())}));
        this.suggestIndexRepository.save(suggestIndex);

//  专辑简介提词
        SuggestIndex albumIntroSuggestIndex = new SuggestIndex();
        albumIntroSuggestIndex.setId(UUID.randomUUID().toString().replaceAll("-",""));
        albumIntroSuggestIndex.setTitle(albumInfoIndex.getAlbumIntro());
        albumIntroSuggestIndex.setKeyword(new Completion(new String[]{albumInfoIndex.getAlbumIntro()}));
        albumIntroSuggestIndex.setKeywordPinyin(new Completion(new String[]{PinYinUtils.toHanyuPinyin(albumInfoIndex.getAlbumIntro())}));
        albumIntroSuggestIndex.setKeywordSequence(new Completion(new String[]{PinYinUtils.getFirstLetter(albumInfoIndex.getAlbumIntro())}));
        this.suggestIndexRepository.save(albumIntroSuggestIndex);

// 专辑主播提词
        SuggestIndex announcerSuggestIndex = new SuggestIndex();
        announcerSuggestIndex.setId(UUID.randomUUID().toString().replaceAll("-", ""));
        announcerSuggestIndex.setTitle(albumInfoIndex.getAnnouncerName());
        announcerSuggestIndex.setKeyword(new Completion(new String[]{albumInfoIndex.getAnnouncerName()}));
        announcerSuggestIndex.setKeywordPinyin(new Completion(new String[]{PinYinUtils.toHanyuPinyin(albumInfoIndex.getAnnouncerName())}));
        announcerSuggestIndex.setKeywordSequence(new Completion(new String[]{PinYinUtils.getFirstLetter(albumInfoIndex.getAnnouncerName())}));
        suggestIndexRepository.save(announcerSuggestIndex);
    }

    /**
     * 下架专辑
     *
     * @param albumId
     */
    @Override
    public void lowerAlbum(Long albumId) {
        albumIndexRepository.deleteById(albumId);
    }
}
